        TITL DAI FIRMWARE 0E79D-0E92C  V1.1
        ORG   :E79D
*
*
*
*******************************************
* EVALUATE ARGUMENTS IN STRING EXPRESSION *
*******************************************
*
* Only '+' or compare with logical result is
* allowed. The right-hand side of a string expres-
* sion is evaluated. If it is not status 02, it is
* moved into the Heap. The stringpointer is saved
* at the varptr location.
* If the variable had already an old value on the
* heap, it is cleared, see further exit conditions.
*
* Entry: (BC): 1.....  Expr. begins with operator.
*              01....  Variable reference.
*              001...  Function call.
*              else    Constant.
* Exit:  BC updated, DEHL corrupted.
*        A: Type (#20).
*
REXPS   LDAX  B         get 1st byte
        RLC
        JC    :E7BD     Jump if 1st byte is operator
        RLC
        JC    :E7B3     Jump if string variable
        RLC
        JC    :E9D9     Jump if string function
 REM
* If string constant:
 REM
        MVI   E,:00     Status: constant
        INX   B
        LDAX  B         Get string length
        MOV   H,B       ) Stringpntr in HL
        MOV   L,C       )
        JMP   :E190     Abort with BC pnts after STR
 REM
* If string variable:
 REM
RXS10   CALL  :E963     Get varptr in HL, T/L in A
        MOV   E,M       )
        INX   H         ) Stringaddr in DE
        MOV   D,M       )
        XCHG            and in HL
        MVI   E,:01     Status: variable
        RET
 REM
* If string operation:
 REM
ROSTR   LDAX  B         Get 1st byte
        INX   B
        PUSH  PSW
        PUSH  D
        CALL  :E79D     Evaluate string expression
        POP   PSW
        MOV   D,A
        POP   PSW
        PUSH  H         Remember it
        MOV   D,E       Type in D
        PUSH  PSW
        PUSH  D
        CALL  :E79D     Eval 2nd string expr
        POP   PSW
        MOV   D,A
        POP   PSW
        PUSH  B         Save it
        MOV   B,H
        MOV   C,L
        POP   H
        XTHL            Save program pointer
        PUSH  B         )
        MOV   B,D       )
        MOV   C,E       ) Re-arrange registers
        XCHG            )
        POP   H         )
        CPI   :C0       Operator is '+'?
        JZ    :E7EB     Then append 2 strings
 REM
* If string compare:
 REM
        CALL  :D121     Compare 2 strings
        CALL  :E7F8     Returns operands if temp
        POP   B         restore
        MOV   E,A       Opcode in E
        JMP   :E933     Evaluate the compare
 REM
* If operator is '+':
 REM
ROS10   PUSH  H
        CALL  :D106     Make 1 string out of 2
        XTHL            Save pntr to result/store
 REM pntr to operand
        CALL  :E7F8     Clean up heap
        POP   H         Pntr to result in HL
        POP   B         Program pntr in BC
        MVI   E,:02     Status: temporary
        RET
*
* CLEAR UP HEAP AFTER STRING OPERATION:
*
* Entry: B,C: Code for 1st resp. 2nd operand.
*             (0=const, 1=var, 2=temp).
*        DE:  Points to 1st operand.
*        HL:  Points to 2nd operand.
* Exit:  DEHL corrupted, AFBC preserved.
*
DROPS   PUSH  PSW
        MOV   A,C       Get code 2nd operand
        CPI   :02       Temporary?
        CZ    :D187     Then clear string in heap
        XCHG
        MOV   A,B       Get code 1st operand
        CPI   :02       Temporary?
        CZ    :D187     Then clear string in heap
        POP   PSW
        RET
*
*********************************
* EVALUATE A NUMERIC EXPRESSION *
*********************************
*
* Entry: BC: Points to a numeric function argument
*            or a numeric expression in program.
* Exit:  BC updated, AFDEHL preserved.
*        Result in MACC.
*
REXNA   PUSH  PSW
        PUSH  D
        PUSH  H
        CALL  :E819     Eval arguments in num expr
        MOV   A,H
        ORA   L
        JZ    :E815     Abort if result in MACC
        RST   4         Else: copy operand to MACC
        DATA  :0C
L0E146  POP   H
        POP   D
        POP   PSW
        RET
*
********************************************
* EVALUATE ARGUMENTS IN NUMERIC EXPRESSION *
********************************************
*
* Checks for constants, functions, variables and
* operators. The right-hand side of the expression
* is therefore evaluated. The value of the variable
* is stored at its varptr location.
*
* Entry: BC:   Points to expression in program.
*        (BC): 1.... Expr begins with operator.
*              01... Variable reference.
*              001.. Function call.
*              Else  Constant.
*        D<>0: MACC must be preserved.
*
REXPN   MVI   D,:00     Set MACC free
 REM
* Called by lower levels:
 REM
RXN10   LDAX  B         Get 1st byte
        RLC
        JC    :E850     Jump if expr starts with
 REM operator
        RLC
        JC    :E96B     Jump if var reference
        RLC
        JC    :E830     Jump if function call
 REM
* If numeric constant:
 REM
        INX   B         Past flag byte
        MOV   H,B       ) HL pnts to constant
        MOV   L,C       )
        INX   B
        INX   B
        INX   B
        INX   B         Program pntr pnts beyond
        RET
 REM
* If numeric function:
 REM
RFUNN   PUSH  D
        MOV   A,D
        ORA   A
        JZ    :E846     Jump if MACC free
        CALL  :C018     Save MACC on stack
        CALL  :E9D9     Evaluate function call
 REM result in MACC
        LXI   H,:0129   Addr WORKE
        RST   4         Copy result to WORKE
        DATA  :0F
        CALL  :C01B     Restore MACC from stack
        POP   D
        RET
RFN10   CALL  :E9D9     Evaluate function call,
 REM result in MACC
        POP   D
        MVI   D,:FF     Set MACC to be preserved
        LXI   H,:0000   Flag 'result in MACC'
        RET
 REM
* If expr begins with numeric operator:
 REM
RONUM   LDAX  B         Get operator
        ANI   :7F       Clip operator bit
        INX   B
        CPI   :1A       Bracket?
        JZ    :E81B     Then ignore it
        DCR   D
        INR   D         Check if D<>0
        CNZ   :C018     Then save MACC on stack
        PUSH  D
        MOV   E,A       Opcode in E
        LXI   H,:E8DC
        PUSH  H         Returnaddr on stack
        CALL  :E819     Get 1st operand
        MOV   A,E       Opcode in A
        ANI   :1F
        CPI   :1C
        JNC   :E89F     Jump if unitary operation
 REM
* If boolean operator:
 REM
        PUSH  H         Save pntr to 1st operand
        CALL  :E81B     Get 2nd operand
        MOV   A,H
        ORA   L
        JNZ   :E87D     Jump if HL pnts to WORKE
        LXI   H,:0129   Addr WORKE
        RST   4         Copy 2nd operand to WORKE
        DATA  :0F
RON10   XTHL
        MOV   A,H
        ORA   L
        JZ    :E885     Jump if 1st operand in MACC
        RST   4         Else copy it from WORKE
        DATA  :0C       to MACC
L0E153  MOV   A,E       Get opcode
        ANI   :1F
        CPI   :10
        JNC   :E8C9     If relational operation
 REM
* If arithmetic operation:
 REM
        CMP   E
        LXI   H,:E8FD   Addr table INT routines
        JNZ   :E897     Jump if INT
        LXI   H,:E8EE   Addr table FPT routines
RON20   MVI   D,:00     Set MACC free
        MOV   E,A       Opcode in E
        DAD   D
        DAD   D
        DAD   D         Find routine in table
        XTHL            Addr routine on stack; pntr
 REM to 2nd operand in HL
        RET             Perform routine
*
* If an unitary operation:
*
* Entry: HL: Points to operand (0 if in MACC).
*        E:  Full opcode.
*        A:  Lower 5 bits opcode.
*        Returnaddr on stack (E8DC).
* Exit:  Result in MACC.
*        ABCDEHL preserved
*
RON40   PUSH  PSW
        MOV   A,H
        ORA   L
        JZ    :E8A7     If operand in MACC
        RST   4         Else: operand in MACC
        DATA  :0C
L0E156  POP   PSW
        RZ              Ready if unitary '+'
        CMP   E         Bits 6,7 opcode 0?
        JZ    :E8BE     Then change MACC to INT
        CPI   :1E       INOT?
        JC    :E8BB     Then change sign MACC (INT)
        JNZ   :E8B8     Then convert MACC to FPT
        RST   4         Perform INOT
        DATA  :6C
        RET
*
L0E157  RST   4         Convert MACC to FPT
        DATA  :4B
        RET
*
RON44   RST   4         Change sign MACC (INT)
        DATA  :60
        RET
*
RON45   CPI   :1D
        JZ    :E8C6     Then change sign MACC (FPT)
        RST   4         Convert MACC to INT
        DATA  :48
        RET
*
RON49   RST   4         Change sign MACC (FPT)
        DATA  :1B
        RET
*
* If relational numeric operation:
*
* Entry: 1st operand in MACC, 2nd operand on stack.
*        E: Full opcode.
*        A: Lowest 5 bits opcode.
* Exit:  BC preserved, DEHL corrupted.
*
RON50   POP   H         Get pntr 2nd operand
        CMP   E
        JZ    :E8D6     Jump if FPT
        CALL  :C015     Compare 2 INT numbers
RON55   POP   H         Kill returnaddr
        POP   H         Kill saved DE
        JMP   :E933     Return logical result
RON60   CALL  :C00C     Compare 2 FPT numbers
        JMP   :E8D1
*
* MOVE OPERAND:
*
* REX.. routines return here after operation.
* Moves operand to proper location after computing.
*
* Entry: DE and returnaddress on stack.
* Exit:  ABC preserved.
*
RON30   POP   D
        DCR   D
        INR   D         Check D=0 (MACC free)
        MVI   D,:FF
        LXI   H,:0000   Flag 'result in MACC'
        RZ              Abort if operand in MACC
        LXI   H,:0129   Addr WORKE
        RST   4         Copy MACC to WORKE
        DATA  :0F
        CALL  :C01B     Restore old MACC from stack
        RET
*
* TABLE OF JUMPS TO INT/FPT OPERATOR ROUTINES:
*
ROFTAB  RST   4
        DATA  :00       MFADD; +
        RET
*
        RST   4
        DATA  :03       MFSUB; -
        RET
*
        RST   4
        DATA  :09       MFDIV; /
        RET
*
        RST   4
        DATA  :06       MFMUL; *
        RET
*
        RST   4
        DATA  :24       MPWR ; ^
        RET
*
ROITAB  RST   4
        DATA  :4E       MIADD; +
        RET
*
        RST   4
        DATA  :51       MISUB; -
        RET
*
        RST   4
        DATA  :57       MIDIV; /
        RET
*
        RST   4
        DATA  :54       MIMUL; *
        RET
*
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
        DATA  :00
*
        RST   4         MIAND
        DATA  :63
        RET
*
        RST   4         MIOR
        DATA  :66
        RET
*
        DATA  :00
        DATA  :00
        DATA  :00
*
        RST   4         MIXOR
        DATA  :69
        RET
*
        RST   4         MSHL
        DATA  :6F
        RET
*
        RST   4         MSHR
        DATA  :72
        RET
*
        RST   4         MIREM
        DATA  :5A
        RET
*
*
*
        END
